#include "editctrls.h"
#include <commctrl.h>
#include "winassert.h"

namespace win
{
	using std::runtime_error;
	int TextControl::s_defaultHeight = -1;

	void TextControl::ResetFontHeight()
	{
		s_defaultHeight = -1;
	}
	
	bool TextControl::IsModified()
	{
		return ::SendMessage(_hwnd,EM_GETMODIFY,0,0) == TRUE;
	}

	TextControl::TextControl()
	{
		_buffer = 0;
	}

	const char * TextControl::GetText()
	{
		ASSERT(_hwnd);
		FreeBuffer();
  		int s = GetTextLength() + 1;
    	_buffer = new char[s];
     	Window::GetText(_buffer,s);
      	return _buffer;
	}
	
	void TextControl::Move(const int left, const int top, const int width)
	{
//		RECT r;
//		::GetClientRect(_hwnd,&r);
    	::MoveWindow(_hwnd,left,top,width,DefaultHeight(),FALSE);

	}
	
	void TextControl::FreeBuffer()
	{
		if (_buffer)
		{
			delete[] _buffer;
			_buffer = 0;
		}
	}
	
	int TextControl::DefaultHeight()
	{
		return LineHeight() * NumLines();
	}
	
	int TextControl::NumLines()
	{
		return 1;		
	}
	
	int TextControl::LineHeight()
	{
		if (s_defaultHeight == -1)
		{
	      TEXTMETRIC tm;
	      HDC hdc = GetDC(_hwnd);
	      GetTextMetrics(hdc,&tm);
	      ReleaseDC(_hwnd,hdc);
	      s_defaultHeight = MulDiv(12,tm.tmHeight,8);     
		}
		return s_defaultHeight;
	}
	
	TextControl::~TextControl()
	{
		FreeBuffer();
	}

	void EditBox::Create(Window &parent, const int child_index, const Rect& pos)
	{
		HINSTANCE hinst = parent.AppInstance();
		_hwnd = CreateWindowEx(0, "EDIT", (LPSTR) NULL,
					WS_CHILD | WS_VISIBLE | WS_TABSTOP |WS_BORDER
     			 | ES_AUTOHSCROLL,
		   	 	pos.left, pos.top, pos.Width(), CW_USEDEFAULT, 
        		parent.GetHandle(), (HMENU) child_index,
				hinst, NULL);
		if (_hwnd == 0)
		  		throw runtime_error("CreateWindowEx failed");
	}
	
	
	void MultiLineEdit::Create(Window &parent, const int child_index)
	{
		HINSTANCE hinst = parent.AppInstance();
		_hwnd = CreateWindowEx(0, "EDIT", (LPSTR) NULL,
					 WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP |
                    ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL ,
		   	 	0, 0, 0, CW_USEDEFAULT,
        		parent.GetHandle(), (HMENU) child_index,
				hinst, NULL);
		if (_hwnd == 0)
		  		throw runtime_error("CreateWindowEx failed");
		::SendMessage(_hwnd,EM_FMTLINES,FALSE,0);   		
	}

	void ComboBox::Create(Window &parent, const int child_index, const eBoxType type)
	{
		HINSTANCE hinst = parent.AppInstance();
		_hwnd = CreateWindowEx(0, "COMBOBOX", (LPSTR) NULL,
					 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
      				 CBS_AUTOHSCROLL	 | type,
		   	 	0, 0, 0, CW_USEDEFAULT,
        		parent.GetHandle(), (HMENU) child_index,
				hinst, NULL);
		if (_hwnd == 0)
		  		throw runtime_error("CreateWindowEx failed");
		ResetContent();
	}
	
	void ComboBox::Add(const char* item)
	{
		::SendMessage(_hwnd, CB_ADDSTRING,0,(LPARAM) item);
	}
	
	void ComboBox::ResetContent()
	{
		::SendMessage(_hwnd,CB_RESETCONTENT,0,0);
	}
	
	void ComboBox::SelectString(const char * str)
	{
		::SendMessage(_hwnd, CB_SELECTSTRING,0,(LPARAM) str);
	}

	bool ComboBox::IsModified()
	{
		return true;
		/* TODO (#9#): See how we can determine whether a combo box has 
		               been modified.
		               Also check the "callers" of this method.
		               This does not cause any bugs -- code will be a bit 
		               cleaner. */
	}

	int ComboBox::NumLines()
	{
		return 5;
	}

}
